/**
 * @returns {Generator<string, "f", void>}
 */
function* foo() {
  yield "a";
  yield "b";
  yield "c";
  return yield* bar();
}

/**
 * @returns {Generator<string, "f", void>}
 */
function* bar() {
  yield "c";
  yield "d";
  yield "e";
  return "f";
}

const f = foo();
while (true) {
  const { value, done } = f.next();
  if (done) {
    break;
  }
  console.log(value);
}

// Expected output: "abc"

class Raisable {
  now = 0;

  src = [1, 2, 3];

  i = 0;

  /**
   * @returns {Generator<number, number, void>}
   */
  *yields() {
    while (true) {
      yield (this.now = this.src[this.i++]);
      console.log("now", this.now);
      if (this.i === this.src.length) {
        break;
      }
    }
    return 0;
  }

  static run() {
    const r = new Raisable();
    const y = r.yields();
    do {
      const n = y.next();
      console.log("n", n);
      if (n.done) {
        break;
      }
      // eslint-disable-next-line no-constant-condition
    } while (1);
  }
}
Raisable.run();

/**
 * @param {number} value
 * @returns {Generator<number, void, number>}
 */
function* counter(value) {
  /**
   * @desc 记录 进行了多少次
   * @type {number}
   */
  let step;

  while (true) {
    step = yield value++;
    if (step) {
      value += step;
    }
  }
}

const generatorFunc = counter(0);
console.log(generatorFunc.next().value); // 0
console.log(generatorFunc.next().value); // 1
console.log(generatorFunc.next().value); // 2
console.log(generatorFunc.next().value); // 3
console.log(generatorFunc.next(10).value); // 14
console.log(generatorFunc.next().value); // 15
console.log(generatorFunc.next(10).value); // 26
